package com.huang.config.exception;

import com.huang.enums.ResultStatus;
import com.huang.exception.ServiceException;
import com.huang.vo.ResultObject;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.converter.HttpMessageNotReadableException;
import org.springframework.validation.BindException;
import org.springframework.web.HttpRequestMethodNotSupportedException;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.MissingServletRequestParameterException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import org.springframework.web.method.annotation.MethodArgumentTypeMismatchException;

import java.nio.file.AccessDeniedException;

@Slf4j
@RestControllerAdvice
public class GlobalExceptionHandler {

    /* ----------- 请求方法有误 ------------ */
    @ExceptionHandler(HttpRequestMethodNotSupportedException.class)
    public ResultObject<Boolean> methodNotAllowedExceptionHandler(HttpRequestMethodNotSupportedException ex) {
//        log.info("[405 METHOD NOT ALLOWED] AccountId: {}", getAccountId(), ex);
        return ResultObject.fail(ResultStatus.SYS_METHOD_NOT_ALLOWED);
    }

    /* ----------- 参数格式有误 ------------ */
    @ExceptionHandler(HttpMessageNotReadableException.class)
    public ResultObject<Boolean> messageNotReadableExceptionHandler(HttpMessageNotReadableException ex) {
//        log.info("[400 BAD REQUEST] AccountId: {}", getAccountId(), ex);
        return ResultObject.fail(ResultStatus.SYS_PARAMETER_NOT_VALID);
    }

    /* ----------- 参数类型错误 ------------ */
    @ExceptionHandler(MethodArgumentTypeMismatchException.class)
    public ResultObject<Boolean> methodArgumentTypeMismatchHandler(MethodArgumentTypeMismatchException ex) {
//        log.info("[400 BAD REQUEST] AccountId: {}", getAccountId(), ex);
        return ResultObject.fail(ResultStatus.SYS_PARAMETER_NOT_VALID);
    }

    /* ----------- 缺少必要参数 ------------ */
    @ExceptionHandler(MissingServletRequestParameterException.class)
    public ResultObject<Boolean> missingServletRequestParameterException(MissingServletRequestParameterException ex) {
//        log.info("[400 BAD REQUEST] AccountId: {}", getAccountId(), ex);
        return ResultObject.fail(ResultStatus.SYS_PARAMETER_REQUIRED);
    }

    /* ----------- 参数校验不通过 ------------ */
    @ExceptionHandler(MethodArgumentNotValidException.class)
    public ResultObject<Boolean> bizExceptionHandler(MethodArgumentNotValidException ex) {
//        log.info("[400 BAD REQUEST] AccountId: {}", getAccountId(), ex);
        return ResultObject.fail(ResultStatus.SYS_PARAMETER_NOT_VALID);
    }

    /* ----------- 参数校验不通过 ------------ */
    @ExceptionHandler(BindException.class)
    public ResultObject<Boolean> bindHandler(BindException ex) {
//        log.info("[400 BAD REQUEST] AccountId: {}", getAccountId(), ex);
        return ResultObject.fail(ResultStatus.SYS_PARAMETER_NOT_VALID);
    }

    /* ----------- 认证失败 ------------ */
//    @ExceptionHandler(BadCredentialsException.class)
//    public ResultObject<Boolean> accessDeniedExceptionHandler(BadCredentialsException ex) {
//        log.info("[BAD CREDENTIALS EXCEPTION]", ex);
//        return ResultObject.fail(ResultStatus.AUTH_BAD_CREDENTIALS);
//    }

    /* ----------- 权限不足 ------------ */
    @ExceptionHandler(AccessDeniedException.class)
    public ResultObject<Boolean> accessDeniedExceptionHandler(AccessDeniedException ex) {
//        log.info("[403 FORBIDDEN] AccountId: {}", getAccountId(), ex);
        return ResultObject.fail(ResultStatus.AUTH_FORBIDDEN);
    }

    /* ----------- 业务错误类型 ------------ */
    @ExceptionHandler(ServiceException.class)
    public ResultObject<Boolean> serviceExceptionHandler(ServiceException ex) {
//        log.warn("[SERVICE EXCEPTION] AccountId: {}", getAccountId(), ex);
        return ResultObject.fail(ex.getStatus().getCode(), ex.getMessage());
    }

    /* ----------- 缺省错误类型 ------------ */
    @ExceptionHandler(Exception.class)
    public ResultObject<Boolean> defaultExceptionHandler(Exception ex) {
//        log.error("[UNHANDLED EXCEPTION] AccountId: {}", getAccountId(), ex);
        return ResultObject.fail(ResultStatus.SYS_UNKNOWN_ERROR);
    }

//    private Integer getAccountId() {
//        Object principal = SecurityContextHolder.getContext().getAuthentication().getPrincipal();
//        if (principal instanceof DefaultUserDetails) {
//            DefaultUserDetails userDetails = (DefaultUserDetails) principal;
//            return userDetails.getAccountId();
//        }
//        return null;
//    }
}
